﻿using System;
using System.Linq;
using CardPlay.Model.GameModel.Actions;
using CardPlay.Model.Primitives;

namespace CardPlay.Client.ViewModels
{
    public partial class GameCanvas
    {
        private abstract class FeedbackController : IDisposable
        {
            private PileViewModel _liftedPile;

            protected FeedbackController(GameCanvas canvas, PileViewModel sourcePile)
            {
                Canvas = canvas;
                SourcePile = sourcePile;
            }

            public void Dispose()
            {
                if (SourcePile != null)
                {
                    SourcePile.RestoreLiftedCards(PickupAction);
                    SourcePile = null;
                }

                LiftedPile = null;
            }

            protected GameCanvas Canvas
            {
                get; private set;
            }

            protected RemovePileAction PickupAction 
            { 
                get; set;
            }

            protected PileViewModel SourcePile
            {
                get; set;
            }

            protected PileViewModel LiftedPile
            {
                get { return _liftedPile; }
                set
                {
                    if (LiftedPile != null)
                        Canvas.Remove(LiftedPile);

                    _liftedPile = value;

                    if (LiftedPile != null)
                        Canvas.Add(LiftedPile);
                }
            }
        }

        private class PeekController : FeedbackController
        {
            public PeekController(GameCanvas canvas, GameAction peekAction, PileViewModel sourcePile) : base(canvas, sourcePile)
            {
                PickupAction = new RemovePileAction(peekAction.CardGame, peekAction.Location, 1);

                var liftedPile = sourcePile.SplitFor(PickupAction);
                liftedPile.Offset(new Size(0, -4));

                LiftedPile = liftedPile;
            }
        }

        private class MoveController : FeedbackController, IDraggable
        {
            private readonly IPlayingContext _playingContext;

            public MoveController(GameCanvas canvas, IPlayingContext playingContext, RemovePileAction pickupAction, PileViewModel sourcePile) :
                base(canvas, sourcePile)
            {
                _playingContext = playingContext;

                PickupAction = pickupAction;

                LiftedPile = sourcePile.SplitFor(pickupAction);
                OnDrag(new Size(-2, -2));
            }

            public void OnDrag(Size offset)
            {
                LiftedPile.Offset(offset);
            }

            public void OnDrop()
            {
                var bounds = LiftedPile.Cards.First().Bounds;
                bounds.Offset(LiftedPile.Location);  // Convert from pile coordinates to canvas coordinates

                LiftedPile = null;

                var candidates = Canvas.PilesUnder(bounds).Where(location => location.Path != PickupAction.Location.Path);
                if (!_playingContext.HandleDrop(PickupAction, candidates)) return;

                SourcePile = null;
            }
        }
    }
}